package com.hikvision.open.app.ui.download

import android.util.Log
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.hikvision.hatomplayer.PlayCallback
import com.hikvision.hatomplayer.util.FileUtil
import com.hikvision.hatomplayer.util.HikDownloader
import com.hikvision.hpsclient.WaterConfig
import com.hikvision.hpsclient.WaterOffset
import com.hikvision.open.app.model.PlayResult
import com.hikvision.open.app.utils.FileIOUtils
import com.hikvision.open.app.utils.FileTransClient
import com.hikvision.open.app.utils.FileUtils
import com.hikvision.open.app.utils.MyUtils
import com.hikvision.open.app.utils.Utils
import com.hikvision.open.app.utils.launch
import com.hikvision.open.app.utils.launchOnUI
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.withContext
import java.io.File
import java.io.FileNotFoundException

/**
 * <p> 录像下载ViewModel </p>
 * @author 段自航 2021/7/15 15:43
 * @version V1.0
 */
class DownloadViewModel : ViewModel() {

    /**
     * 下载结果
     */
    private val _downloadResult = MutableLiveData<PlayResult>()
    val downloadResult: LiveData<PlayResult> = _downloadResult

    var filePath = ""

    /**
     * 下载客户端
     */
    private val downloadClient: HikDownloader by lazy {
        HikDownloader()
    }


    /**
     * 录像转码结果
     */
    private val _saveResult = MutableLiveData<Int>()
    val saveResult: LiveData<Int> = _saveResult

    /**
     * 录像转码客户端
     */
    private val client by lazy {
        FileTransClient()
    }

    private var downloading = false

    /**
     * 开启下载
     */
    fun startDownload(
        url: String,
        startTime: String,
        endTime: String,
        token: String
    ) {
        launchOnUI {
            withContext(Dispatchers.IO) {
                val offset = arrayListOf<WaterOffset>()
                val fontWidth = 5
                val fontHeight = 35
                val content = arrayListOf<String>()
                content.add("自定义水印")
                offset.add(WaterOffset(500, 160))
                val waterConfig = WaterConfig(1, content, offset, fontWidth, fontHeight)
                filePath = MyUtils.getLocalRecordPath(Utils.getApp())
                downloadClient.startDownload(
                    url,
                    token,
                    startTime,
                    endTime,
                    waterConfig,
                    object : PlayCallback.DownloadDataCallback {
                        override fun onError(opt: Int, errorCode: Int) {
                            val file = FileUtils.getFileByPath(filePath)
                            file.delete()
                            _downloadResult.postValue(
                                PlayResult(
                                    status = PlayCallback.Status.FAILED,
                                    errorCode = "${errorCode ?: "-1"})"
                                )
                            )
                        }

                        override fun onData(dataType: Int, data: ByteArray?, length: Int) {
                            Log.i("DownloadViewModel", "onData, dataType: $dataType")
                            if (dataType == 0x0001 || dataType == 0x0002) {
                                Log.i("DownloadViewModel", "downloading start")
                                downloading = true
                                //下载中
                                _downloadResult.postValue(PlayResult(status = PlayCallback.Status.SUCCESS))
                                val file = FileUtils.getFileByPath(filePath)
                                FileIOUtils.writeFileFromBytesByStream(file, data, true)
                            } else if (dataType == 0x0067) {
                                // 下载异常结束通知标识
                                val file = FileUtils.getFileByPath(filePath)
                                file.delete()
                                _downloadResult.postValue(
                                    PlayResult(
                                        status = PlayCallback.Status.EXCEPTION,
                                        errorCode = "-1"
                                    )
                                )
                            } else if (dataType == 0x0064) {
                                if (downloading) {
                                    Log.i("DownloadViewModel", "downloading finish")
                                    downloading = false
                                    // 回放、下载或倒放结束标识
                                    _downloadResult.postValue(PlayResult(status = PlayCallback.Status.FINISH))
                                    transVideo()
                                }
                            }
                        }
                    })
            }
        }
    }

    /**
     * 关闭下载
     */
    fun stopDownload() {
        launchOnUI {
            withContext(Dispatchers.IO) {
                downloadClient.stopDownload()
                transVideo()
            }
        }
    }

    /**
     * 转码视频
     */
    fun transVideo() {
        launch {
            flow {
                val videoFile = File(filePath)
                val targetPath = MyUtils.getLocalRecordPath(Utils.getApp())
                if (!FileUtil.isFileExists(targetPath)) {
                    if (!realTransVideo(videoFile, targetPath)) {
                        //触发异常提示
                        throw FileNotFoundException()
                    } else {
                        FileUtil.deleteFile(filePath)
                        filePath = targetPath
                    }
                }
                emit(true)
            }.onStart {
                _saveResult.postValue(0)
            }.flowOn(Dispatchers.IO).catch { e ->
                e.printStackTrace()
                _saveResult.postValue(-1)
            }.collectLatest {
                _saveResult.postValue(1)
            }
        }
    }

    /**
     * 文件转换
     */
    private fun realTransVideo(video: File, targetPath: String): Boolean {
        var result = client.create()
        if (result == -1) {
            return false
        }
        // 不添加水印时，无需转码，直接转封装即可
//        result = client.startNoPrivate(video.absolutePath, targetPath)
        // 添加水印时，需转码，耗时很长
        result = client.start(video.absolutePath, targetPath)
        if (result == -1) {
            return false
        }
        var percent = 0f
        while (percent < 1f) {
            percent = client.getProgress()
        }
        client.stop()
        client.destroy()
        return true
    }


}